angular.module('App')

.factory('bluetoothHelper', ['$cordovaBluetoothSerial', '$q', '$timeout', '$window', function ($cordovaBluetoothSerial, $q, $timeout, $window) {
	return {
		buffer: [],
		callback: {
			fn: undefined,
			length: 1
		},
		disconnect: function () {
			var deferred = $q.defer();
			$cordovaBluetoothSerial
				.isConnected()
				.then(function () {
					return $cordovaBluetoothSerial.disconnect();
				}, function () {
					deferred.resolve();
				})
				.then(function () {
					deferred.resolve();
				}, function () {
					deferred.reject('Failed to disconnect.');
				});
			return deferred.promise;
		},
		init: function (deviceName) {
			var obj = this;
			var deferred = $q.defer();
			$cordovaBluetoothSerial
				.isEnabled()
				.then(function () {
					return $cordovaBluetoothSerial.list();
				}, function () {
					deferred.reject('Bluetooth is disabled.');
				})
				.then(function (devices) {
					if (!devices)
						return;
					var filtered = devices.filter(function (device) {
						return device.name === deviceName;
					});
					if (filtered.length === 1) {
						return $cordovaBluetoothSerial.connect(filtered[0].address);
					} else if (filtered.length > 1) {
						deferred.reject('More than one targets found.');
					}
				}, function () {
					deferred.reject('Failed to get bonded devices.');
				})
				.then(function () {
					deferred.resolve();
				}, function () {
					deferred.reject('Failed to connect the target.');
				});
			$window.bluetoothSerial
				.subscribeRawData(function (data) {
					var bytes = new Uint8Array(data);
					for (var i = 0; i < bytes.length; i++) {
						obj.buffer.push(bytes[i]);
					}
					while (obj.buffer.length >= obj.callback.length) {
						if (typeof(obj.callback.fn) === 'function') {
							obj.callback.fn(obj.buffer.splice(0, obj.callback.length));
						}
					}
				});
			return deferred.promise;
		},
		subscribe: function (fn, length) {
			this.callback.fn = fn;
			if (parseInt(length)) {
				this.callback.length = parseInt(length);
			} else {
				this.callback.length = 1;
			}
		},
		write: function (data) {
			var deferred = $q.defer();
			$cordovaBluetoothSerial
				.write(data)
				.then(function () {
					deferred.resolve();
				}, function () {
					deferred.reject('Failed to write.');
				});
			return deferred.promise;
		}
	};
}])

;